#!/usr/bin/env python
# -*- coding: utf-8 -*-

# @Author  : linlvfei2008@126.com
# @Time    : 2019/8/1 11:32
# @Site    : https://gitee.com/chunhuayuyun

import os
import base64
import json
import time
import random
import hashlib
from collections import OrderedDict
from datetime import timedelta, datetime


class Utils:

    @staticmethod
    def get_base64_to_img(text):
        """
        :param text: Base64传入
        :return: 保存图片
        """
        cur_path = os.path.abspath(os.path.dirname(__file__))
        root_path = cur_path[:cur_path.find("ZeroWalletAPIAutoTest\\") + len("ZeroWalletAPIAutoTest\\")]
        img_data = base64.b64decode(text)
        file = open(os.path.join(root_path, "other", "img", "captcha.jpg"), "wb")
        file.write(img_data)
        file.close()

    @staticmethod
    def get_img_to_base64(file_name):
        """
        :param file_name: 文件存放在other/img/test_img  传入文件名包含格式
        :return:
        """
        cur_path = os.path.abspath(os.path.dirname(__file__))
        root_path = cur_path[:cur_path.find("ZeroWalletAPIAutoTest\\") + len("ZeroWalletAPIAutoTest\\")]
        file = open(os.path.join(root_path, "other", "img", "test_img", file_name), "rb")
        base64_data = "data:image/png;base64," + str(base64.b64encode(file.read())).replace("b'", '').replace("'", '')
        return base64_data

    @staticmethod
    def jwt_decode(token_jwt='Bearer eyJ0eXAiOiJ..'):
        """
        将Jwt解析，返回payload里面的内容，payload包含
        sub,iss,aud,jti,iat,nbf,exp,user_id,member_id
        :param token_jwt:
        :return: 返回dict类型的 payload
        """
        try:
            token_jwt = str(token_jwt).split('.')[1] + '=='
            payload = str(base64.b64decode(token_jwt, validate=True))
            payload = json.loads(payload.lstrip('b\'').rstrip('\''))
        except Exception:
            raise ValueError("Jwt_Token解析失败，请检查")

        return payload

    @staticmethod
    def get_random_datetime():
        """
        随机生成一个2019年到2020年的日期
        :return: string 类型时间
        """
        a1 = (2019, 1, 1, 0, 0, 0, 0, 0, 0)  # 设置开始日期时间元组（1976-01-01 00：00：00）
        a2 = (2020, 12, 31, 23, 59, 59, 0, 0, 0)  # 设置结束日期时间元组（1990-12-31 23：59：59）
        start = time.mktime(a1)  # 生成开始时间戳
        end = time.mktime(a2)  # 生成结束时间戳
        # 随机生成10个日期字符串
        t = random.randint(start, end)  # 在开始和结束时间戳中随机取出一个
        date_tuple = time.localtime(t)  # 将时间戳生成时间元组
        date = time.strftime("%Y-%m-%d %H:%M:%S", date_tuple)  # 将时间元组转成格式化字符串（1976-05-21）
        return date

    @staticmethod
    def get_current_datetime():
        """
        :return: string 类型时间
        """
        date_tuple = time.localtime()  # 将时间戳生成时间元组
        date = time.strftime("%Y-%m-%d %H:%M:%S", date_tuple)  # 将时间元组转成格式化字符串（1976-05-21）
        return date

    @staticmethod
    def get_calculate_datetime(day):
        """
        几天后的日期
        :param: to_day 几天后或几天前的时间，传入 整数
        :return: string 类型时间
        """
        if type(day) == int:
            date = (datetime.now() + timedelta(days=day)).strftime("%Y-%m-%d")
            return date
        else:
            raise ValueError("day 类型错误")

    @staticmethod
    def get_params(text):
        """
        :param text: 机票平台订单编号：${ordersn}，第三方订单编号：${air_id}
        :return: ['ordersn', 'air_id']
        """
        params = []
        for items in text.split('$'):
            if items.startswith('{'):
                end_index = items.find('}')
                param_one = items[1:end_index]
                params.append(param_one)

        return params

    @staticmethod
    def get_random_order_no():
        date_tuple = time.strftime("%Y%m%d%H%M%S", time.localtime())
        rnd = str(random.randint(0, 99999999)).rjust(8, "0")
        order_no = "PY" + str(date_tuple) + "_" + rnd
        return order_no

    @staticmethod
    def get_number(min_num, max_num):
        """
        :param min_num: 最小值（包含）
        :param max_num: 最大值（包含）
        :return: 返回4位小数的数字
        """
        num = float(round(random.uniform(min_num, max_num), random.randint(0, 4)))
        return num

    # 接口返回值与Sql查询金额字段对比时,防止0 != 0.00错误出现
    @staticmethod
    def pre_zero(num):
        if num == '0.00':
            return 0
        return num

    @staticmethod
    def text_to_md5(text):
        """
        :param text: 文本类型
        :return: md5text
        """
        if type(text) == str:
            # 生成一个md5对象
            m1 = hashlib.md5()
            # 使用md5对象里的update方法md5转换
            m1.update(text.encode("utf-8"))
            md5_text = m1.hexdigest()
            return md5_text
        else:
            raise ValueError("请传入Str类型数据！")

    @staticmethod
    def get_distance(lng1, lat1, lng2, lat2):
        from math import radians, cos, sin, asin, sqrt
        # lng1,lat1,lng2,lat2 = (120.12802999999997,30.28708,115.86572000000001,28.7427)
        lng1, lat1, lng2, lat2 = map(radians, [float(lng1), float(lat1), float(lng2), float(lat2)])  # 经纬度转换成弧度
        dlon = lng2 - lng1
        dlat = lat2 - lat1
        a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2
        distance = 2 * asin(sqrt(a)) * 6371 * 1000  # 地球平均半径，6371km
        distance = round(distance / 1000, 3)
        return distance

    @staticmethod
    def param_encrypt_df(data_param, third_type):

        """
        笛风加密算法
        :param: data_param：传入DICT入参
        :param: third_type: 类型，酒店或者机票hotel,air
        :return:  返回加密请求参数，可直接使用参数请求（类型dict）
        """
        if third_type == 'hotel':
            api_key = 'hoteltest'
            secret_key = 'aaaaaaaa'
        elif third_type == 'air':
            # api_key = '233963_DomesticFlightNew'
            # secret_key='LwBwolJwjqA9tEnoaU6P'
            api_key = 'dflighttest'
            secret_key = 'aaaaaaaa'
        elif third_type == 'air_old':
            # api_key = '233963_DomesticFlight'
            # secret_key = 'QKBvoKKtfOfNkEQQFNyI'
            api_key = 'jdtest'
            secret_key = 'aaaaaaaa'
        else:
            raise ValueError("Type错误！")

        if type(data_param) == dict:

            timestamp = Utils.get_current_datetime()
            data_param['apiKey'] = api_key
            data_param['timestamp'] = timestamp

            sort_param_list = Utils.sort_param(data_param)[1]

            # 转换成用&连接的字符串
            sort_param_list = sorted(sort_param_list, key=lambda x: x, reverse=False)

            str_data = ''
            for item in sort_param_list:
                str_data += item + '&'

            # md5
            sign = Utils.text_to_md5(secret_key + '&' + str_data + secret_key).upper()

            # 移除项
            data_param.pop('apiKey')
            data_param.pop('timestamp')

            # 拼接最终请求参数
            secret_param = dict()
            secret_param['apiKey'] = api_key
            secret_param['sign'] = sign
            secret_param['timestamp'] = timestamp
            secret_param['data'] = data_param

            return secret_param
        else:
            raise ValueError("请传入dict类型")

    @staticmethod
    def sort_param(data_param):
        """
        :param data_param:
        :return:order_dict，order_list
        """

        # 最终需要的参数列表
        order_list = []
        # 暂存用dict
        order_dict = OrderedDict()

        # 遍历参数
        for key, value in data_param.items():

            # 可能存在相同的key所以用list存放
            order_dict[key] = []

            if type(value) == list:
                for item in value:
                    return_dict = Utils.sort_param(item)
                    for list_key, list_value in return_dict[0].items():
                        order_list.append(str(list_key) + '=' + str(*list_value))

            elif type(value) == dict:
                return_dict = Utils.sort_param(value)
                for dict_key, dict_value in return_dict[0].items():
                    order_list.append(str(dict_key) + '=' + str(dict_value))
            else:
                if value == '':
                    # 跳过为空参数
                    pass
                else:
                    order_list.append(str(key) + '=' + str(value))
                    order_dict[key].append(value)

        return order_dict, order_list

    @staticmethod
    def get_timestamp_to_datetime(timestamp):
        """
        时间戳转日期型
        :param timestamp: 时间戳1557502800
        :return: 日期型日期
        """
        from time import localtime, strftime
        time_array = localtime(timestamp)
        date_time = strftime("%Y-%m-%d %H:%M:%S", time_array)
        return date_time

    @staticmethod
    def get_datetime_to_timestamp(datetime):
        """
        日期型转时间戳
        :param datetime:
        :return: 时间戳格式日期
        """
        pass


if __name__ == '__main__':
    # token = 'Bearer ***'
    utils = Utils()
    # a = utils.jwt_decode(token)
    print(utils.get_timestamp_to_datetime(0))
    # param = dict()
    # param['adultQuantity'] = 1
    # param['childQuantity'] = 1
    # param['babyQuantity'] = 1
    # segment_list = []
    # segment = dict()
    # segment['departDate'] = Utils.get_calculate_datetime(1)
    # segment['aCityIataCode'] = 'SHA'
    # segment['dCityIataCode'] = 'BJS'
    # segment_list.append(segment)
    # param['segmentList'] = segment_list
    # # 0：所有, 1：经济舱, 2：公务舱, 3：头等舱
    # param['cabinClass'] = "0"
    #
    # utils.param_encrypt_df(param, 'air')
